package com.ziven.common.widget.value;

import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ziven.easygo.util.Carry;
import com.ziven.easygo.util.EasyUtils;
import com.ziven.easygo.util.Nulls;
import com.ziven.easygo.util.Standard;
import com.ziven.easygo.util.ViewHelper;

/**
 * @author Ziven
 */
public abstract class Value implements Standard {

    public Object id;
    public int resId;
    public Object value;
    public int viewId = View.NO_ID;

    public Runnable before;
    public Runnable after;

    public Value setId(Object id) {
        this.id = id;
        return this;
    }

    public Value resId(int resId) {
        this.resId = resId;
        return this;
    }

    public Value value(Object value) {
        this.value = value;
        return this;
    }

    public Value viewId(int viewId) {
        this.viewId = viewId;
        return this;
    }

    public  <T> boolean value(@NonNull Class<T> cls, @NonNull Carry<T> carry) {
        return EasyUtils.instanceDo(value, cls, carry);
    }

    @NonNull
    public <T> T value(@NonNull Class<T> cls) throws ClassCastException {
        return EasyUtils.instanceDo(value, cls);
    }

    public  <T> boolean myself(@NonNull Class<T> cls, @NonNull Carry<T> carry) {
        return EasyUtils.instanceDo(this, cls, carry);
    }

    @NonNull
    public <T> T myself(@NonNull Class<T> cls) throws ClassCastException {
        return EasyUtils.instanceDo(this, cls);
    }

    public void takeEffect(View view) {
        view = viewId == View.NO_ID ? view : view.findViewById(viewId);
        if(view != null) {
            Nulls.of(before).doNotNull(Runnable::run);
            takeEffect(ViewHelper.create(view));
            Nulls.of(after).doNotNull(Runnable::run);
        }
    }

    public Value beforeEffect(Runnable before) {
        this.before = before;
        return this;
    }

    public Value afterEffect(Runnable after) {
        this.after = after;
        return this;
    }

    /**
     * Take Effect
     * @param helper ViewHelper
     */
    protected abstract void takeEffect(@NonNull ViewHelper<? extends View> helper);

    public boolean isNullValue() {
        return false;
    }

    public Value copy(@NonNull Value v) {
        if(!v.isNullValue()) {
            v.id = id;
            v.resId = resId;
            v.value = value;
            v.viewId = viewId;
        }
        return this;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if(this == obj) {
            return true;
        }
        if(!(obj instanceof Value)) {
            return false;
        }
        Value objValue = (Value) obj;
        if(id == null || objValue.id == null) {
            return false;
        }
        return id.equals(objValue.id);
    }

    @NonNull
    @Override
    public String toString() {
        return "Value{" +
                "id=" + id +
                ", resId=" + resId +
                ", value=" + value +
                ", viewId=" + viewId +
                '}';
    }
}
